<template>
  <div class="map-box">
    <div id="cesiumContainer" ref="cesRef"></div>
  </div>
</template>

<script>
import * as Cesium from 'cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'
import * as turf from '@turf/turf'
import ElementPlus from 'element-plus'
import locale from 'element-plus/lib/locale/lang/zh-cn'
import * as echarts from 'echarts'
// import installIcons from '@/icons'
import { onMounted, ref, defineExpose, defineEmits, createApp, h } from 'vue'
import { cartesian3ToDegree, MeasureDistance } from '@/utils/gis/GisToolsUtil'
import { MeasureTools } from '@/utils/gis/MeasureTools'
import normalMarker from '@/assets/images/gis/marker_normal.png'

import getCesiumHeat from '@/utils/gis/CesiumHeat.js'

export default {
  name: 'MapFrame'
}
</script>

<script setup>
// 自定义echart自适应指令

const billboards = {}
const labels = {}
const points = {}
const polylines = {}
const polygons = {}
const primitiveName = []

const pickPosition = ref({})
const HANDLER = '_vue_echarts_resize_handler'

function unbind(el) {
  window.removeEventListener('resize', el[HANDLER])
  delete el[HANDLER]
}

function bind(el) {
  // binding
  unbind(el)
  el[HANDLER] = function () {
    const chart = echarts.getInstanceByDom(el)
    if (!chart) {
      return
    }

    chart.resize()
  }
  window.addEventListener('resize', el[HANDLER])
}

const cesRef = ref(null)
let viewer = null
let handler = null
const basemap = {}
let handleMeasure = null
const measures = []
let bufferEntity = []
const BIM = {}
const billboardStyle = {
  width: 27,
  height: 37
}
let VA = null //通视分析参数
// let VA_handler = null //通视分析参数
// let VA_positions = [] //通视分析参数
let heightEntity = {}
const heightLightLayer = new Cesium.CustomDataSource('heightLightLayer') //设置高亮图层
const datasource = {} // entities
const addedLayers = []
const flag = {}
let handleSnow = null
let handleRain = null
let handleFog = null
let lineFlow = false //流动线材质开关
let lineFlicker = false //闪烁线材质开关
let wallDiffuse = false //发光墙材质开关
let previousPickedEntity = null
const emits = defineEmits([
  'openPopupBox',
  'getClickPoint',
  'atLonghu',
  'atBuilding'
])
const tile3dUrl =
  'http://36.7.170.39:8026/oss-file-service/hf_building/tileset.json' //'http://localhost:8088/hf_building/tileset.json';
const terrainUrl = 'http://localhost:8088/ah_dem'
const tiandituTk = '607bc7f8763baa49129cdc2f9b68ecc7' //天地图许可68dd3ce7dfcb4d2b804b8676bcc49b8c
// 服务负载子域
const subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']

const initMap = () => {
  Cesium.Ion.defaultAccessToken =
    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyODM4N2ViZi0wZGE1LTRiNDYtOGQ3Yi03MmIzOTQzNjBmMDUiLCJpZCI6NjgxMTAsImlhdCI6MTYzMjM1OTAyN30.byo1Xq5SVYTtc2cUhFDJmyupFjZ4lM9cs7BrFRW2-Co'

  /* const imageryViewModels = [];
   imageryViewModels.push(new Cesium.ProviderViewModel({
     name: 'Open\u00adStreet\u00adMap',
     iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/openStreetMap.png'),
     tooltip: 'OpenStreetMap',
     creationFunction: function () {
       return new Cesium.OpenStreetMapImageryProvider({
         url: 'https://a.tile.openstreetmap.org/'
       });
     }
   }));

   imageryViewModels.push(new Cesium.ProviderViewModel({
     name: 'Natural Earth\u00a0II',
     iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/naturalEarthII.png'),
     tooltip: 'NaturalEarthII',
     creationFunction: function () {
       return new Cesium.TileMapServiceImageryProvider({
         url: Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')
       });
     }
   }));

   imageryViewModels.push(new Cesium.ProviderViewModel({
     name: '天地图影像',
     iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/mapboxSatellite.png'),
     tooltip: '天地图',
     creationFunction: function () {
       return new Cesium.WebMapTileServiceImageryProvider({
         //影像底图
         url: "http://t{s}.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" + tiandituTk,
         // url: "http://localhost:9001/TdtSatellite/L{TileMatrix}/{TileCol}/{TileRow}.png", //加载本地天地图
         subdomains: subdomains,
         layer: "tdtImgLayer",
         style: "default",
         format: "image/jpeg",
         tileMatrixSetID: "GoogleMapsCompatible", //使用谷歌的瓦片切片方式
         show: true,
         maximumLevel: 12,
       });
     }
   }));*/

  viewer = new Cesium.Viewer('cesiumContainer', {
    shouldAnimate: true,
    geocoder: false, //是否显示geocoder小器件，右上角查询按钮
    sceneModePicker: false, //是否显示3D/2D选择器
    baseLayerPicker: false, //是否显示图层选择器
    navigationHelpButton: false, //是否显示右上角的帮助按钮
    selectionIndicator: false,
    animation: false, //是否创建动画小器件，左下角仪表
    timeline: false, //是否显示时间轴
    homeButton: false, //是否显示Home按钮
    vrButton: false, //VR
    infoBox: false, //是否显示信息框
    fullscreenButton: false, //是否显示全屏按钮
    imageryProvider: new Cesium.MapboxStyleImageryProvider({
      url: 'https://api.mapbox.com/styles/v1',
      username: 'kungleest',
      styleId: 'cl11klj10000815mdz802u16f',
      accessToken:
        'pk.eyJ1Ijoia3VuZ2xlZXN0IiwiYSI6ImNsMTFqbnpreTJzaGYzaXJwbjZveXNxemEifQ.OSM0HViwuSdwnG-IucEGwA',
      tilesize: 256
      // scaleFactor: true,
    })
    // orderIndependentTranslucency: true, //半透明

    // navigationInstructionsInitiallyVisible: false,

    // terrainProvider: Cesium.createWorldTerrain(), //世界地形
    // terrainProvider: new Cesium.EllipsoidTerrainProvider(), //无地形

    /* terrainProvider: new Cesium.CesiumTerrainProvider({
       url: terrainUrl,
       requestVertexNormals: true, //请求照明
       requestWaterMask: false //请求水波纹效果
     }),*/

    // imageryProvider: null,
  })

  //图层控制
  // viewer.baseLayerPicker.viewModel.imageryProviderViewModels.removeAll();
  // viewer.baseLayerPicker.viewModel.imageryProviderViewModels = imageryViewModels;
  basemap.mapbox = viewer.scene.globe.imageryLayers.get(0)
  viewer.scene.imageryLayers.lowerToBottom(basemap.mapbox)

  viewer.cesiumWidget.creditContainer.style.display = 'none' //去掉左下角logo图标
  // viewer.imageryLayers.get(0).show = false; //显示蓝色球；
  // viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);  //3DTilesInspector控制器
  // viewer.scene.globe.baseColor = Cesium.Color.BLUE;

  // 注销默认鼠标点击事件
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  )
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_CLICK
  )

  //判断是否支持图像渲染像素化处理
  if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
    viewer.resolutionScale = window.devicePixelRatio
  }
  viewer.scene.fxaa = true //开启fxaa能够启用图片抗锯齿,可能会导致图片清晰度降低
  viewer.scene.postProcessStages.fxaa.enabled = true ////抗锯齿，是：文字清晰
  viewer.scene.fog.enabled = false //启用雾为true，否则为false
  viewer.scene.globe.depthTestAgainstTerrain = false //开启或关闭地形遮盖
  // viewer.scene.globe.enableLighting = true; //模拟真实光照
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  viewer.dataSources.add(heightLightLayer)
  // viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);
}

/**
 * 选择底图
 **/
const selectBaseMap = (id) => {
  const layers = viewer.scene.imageryLayers
  if (id === 'mapbox') {
    basemap.mapbox = layers.addImageryProvider(
      new Cesium.MapboxStyleImageryProvider({
        url: 'https://api.mapbox.com/styles/v1',
        username: 'kungleest',
        styleId: 'cl11klj10000815mdz802u16f',
        accessToken:
          'pk.eyJ1Ijoia3VuZ2xlZXN0IiwiYSI6ImNsMTFqbnpreTJzaGYzaXJwbjZveXNxemEifQ.OSM0HViwuSdwnG-IucEGwA',
        tilesize: 256,
        scaleFactor: true
      })
    )
    layers.raiseToTop(basemap.mapbox)
    if (Cesium.defined(basemap.img)) {
      basemap.img.show = false
      basemap.cia.show = false
    } else if (Cesium.defined(basemap.vec)) {
      basemap.vec.show = false
      basemap.cva.show = false
    }
  } else if (id === 'mapbox_blue') {
    basemap.mapbox = layers.addImageryProvider(
      new Cesium.MapboxStyleImageryProvider({
        url: 'https://api.mapbox.com/styles/v1',
        username: 'longqun',
        styleId: 'ckw2xujrr0ap315s4h6vn6bxu',
        accessToken:
          'pk.eyJ1IjoibG9uZ3F1biIsImEiOiJja3ZnMnpqOXMyNTRnMzFzMXl5OTdjZjBiIn0.44DULmZ14BSaaPSHY9xPog',
        tilesize: 256,
        scaleFactor: true
      })
    )
    layers.raiseToTop(basemap.mapbox)
    if (Cesium.defined(basemap.img)) {
      basemap.img.show = false
      basemap.cia.show = false
    } else if (Cesium.defined(basemap.vec)) {
      basemap.vec.show = false
      basemap.cva.show = false
    }
  } else if (id === 'vec') {
    if (Cesium.defined(basemap.vec)) {
      basemap.vec.show = true
      basemap.cva.show = true
    } else {
      basemap.vec = layers.addImageryProvider(
        new Cesium.WebMapTileServiceImageryProvider({
          url: 'http://t0.tianditu.gov.cn/vec_w/wmts?tk=' + tiandituTk,
          layer: 'vec',
          style: 'default',
          tileMatrixSetID: 'w',
          format: 'tiles',
          maximumLevel: 18
        })
      )
      basemap.cva = layers.addImageryProvider(
        new Cesium.WebMapTileServiceImageryProvider({
          url: 'http://t1.tianditu.gov.cn/cva_w/wmts?tk=' + tiandituTk,
          layer: 'cva',
          style: 'default',
          tileMatrixSetID: 'w',
          format: 'tiles',
          maximumLevel: 18
        })
      )
    }
    layers.raiseToTop(basemap.vec)
    layers.raiseToTop(basemap.cva)
    if (Cesium.defined(basemap.mapbox)) {
      basemap.mapbox.show = false
    }
  } else if (id === 'img') {
    if (Cesium.defined(basemap.img)) {
      basemap.img.show = true
      basemap.cia.show = true
    } else {
      basemap.img = layers.addImageryProvider(
        new Cesium.WebMapTileServiceImageryProvider({
          url: 'http://t0.tianditu.gov.cn/img_w/wmts?tk=' + tiandituTk,
          layer: 'img',
          style: 'default',
          tileMatrixSetID: 'w',
          format: 'tiles',
          maximumLevel: 18
        })
      )
      basemap.cia = layers.addImageryProvider(
        new Cesium.WebMapTileServiceImageryProvider({
          url: 'http://t0.tianditu.gov.cn/cia_w/wmts?tk=' + tiandituTk,
          layer: 'cia',
          style: 'default',
          tileMatrixSetID: 'w',
          format: 'tiles',
          maximumLevel: 18
        })
      )
    }
    layers.raiseToTop(basemap.img)
    layers.raiseToTop(basemap.cia)
    if (Cesium.defined(basemap.mapbox)) {
      basemap.mapbox.show = false
    }
  }
}

/***
 * 下雪特效
 */

// const showSnowEffect = (size, speed) => {
//   handleSnow = new SnowEffect(viewer, {
//     snowSize: size, // 雪花大小
//     snowSpeed: speed // 雪速
//   })
// }

/***
 * 关闭下雪特效
 */
const clearSnowEffect = () => {
  if (handleSnow) {
    handleSnow.destroy()
  }
  handleSnow = null
}

/***
 * 下雨特效
 */
// const showRainEffect = (angle, size, speed) => {
//   handleRain = new RainEffect(viewer, {
//     tiltAngle: angle, //倾斜角
//     snowSize: size, // 雪花大小
//     snowSpeed: speed // 雪速
//   })
// }

/***
 * 关闭下雨特效
 */
const clearRainEffect = () => {
  if (handleRain) {
    handleRain.destroy()
  }
  handleRain = null
}

/***
 * 雾特效
 */
// const showFogEffect = (visibility) => {
//   handleFog = new FogEffect(viewer, {
//     visibility: visibility, //能见度
//     color: new Cesium.Color(0.8, 0.8, 0.8, 0.3) // 颜色
//   })
// }

/***
 * 关闭雾特效
 */
const clearFogEffect = () => {
  if (handleFog) {
    handleFog.destroy()
  }
  handleFog = null
}

/* const createHawkEyeMap = () => {
  // 鹰眼地图初始化
  let hawkEyeMap = new HawkEye3DMap(viewer)
  hawkEyeMap.init()
} */

const cartesian2ToDegree = (cartesian2) => {
  const cartesian3 = viewer.scene.globe.pick(
    viewer.camera.getPickRay(cartesian2),
    viewer.scene
  )
  const degree = cartesian3ToDegree(cartesian3)
  return degree
}

//legacy API
const showPoints = (type, show = true) => {
  if (!type) {
    // 没有值
    return
  }
  flag[type] = show
  if (flag[type]) {
    datasource[type] && (datasource[type].show = true)
  } else {
    datasource[type] && (datasource[type].show = false)
  }
}

/**
 * 坐标定位；
 * @param lng //经度
 * @param lat //纬度
 * @param height //高度
 */
const flyToPosition = (
  lng,
  lat,
  height = 1000,
  heading = 0,
  pitch = -45,
  roll = 0,
  duration = 1
) => {
  const offsetY = (height * 0.015) / 1800 //以北半球为例，参考比例高度为1800时，适合的偏移量为0.015
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(lng, lat - offsetY, height), //摄像机的最终位置
    orientation: {
      heading: Cesium.Math.toRadians(heading), // 方位角
      pitch: Cesium.Math.toRadians(pitch), // 倾角
      roll: Cesium.Math.toRadians(roll) //旋转角
    },
    duration: duration //飞行时间
  })
}

const cameraFlyto = ({
  lon,
  lat,
  height,
  orientation = { heading: 0, pitch: -90, roll: 0 },
  duration = 1
}) => {
  viewer.camera &&
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(lon, lat, height), // 经度、纬度、高度
      orientation: {
        heading: Cesium.Math.toRadians(orientation.heading), // 绕垂直于地心的轴旋转
        pitch: Cesium.Math.toRadians(orientation.pitch), // 绕纬度线旋转
        roll: Cesium.Math.toRadians(orientation.roll) // 绕经度线旋转
      },
      duration: duration
    })
}

/**
 * 坐标定位2D视角；
 * @param lng //经度
 * @param lat //纬度
 * @param height //高度
 */
const flyTo2DPosition = (
  lng,
  lat,
  height = 1000,
  heading = 0,
  pitch = -90,
  roll = 0,
  duration = 1
) => {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(lng, lat, height), //摄像机的最终位置
    orientation: {
      heading: Cesium.Math.toRadians(heading), // 方位角
      pitch: Cesium.Math.toRadians(pitch), // 倾角
      roll: Cesium.Math.toRadians(roll) //旋转角
    },
    duration: duration //飞行时间
  })
}

const getCameraInfo = () => {
  const cartesian3 = viewer.camera.position
  const cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
  const lng = Cesium.Math.toDegrees(cartographic.longitude)
  const lat = Cesium.Math.toDegrees(cartographic.latitude)
  const position = [lng, lat]
  const direction = viewer.camera.direction
  const transform = viewer.camera.transform
  const cameraInfo = {
    position,
    height: cartographic.height,
    heading: viewer.camera.heading,
    pitch: viewer.camera.pitch,
    roll: viewer.camera.roll,
    headingDegree: Cesium.Math.toDegrees(viewer.camera.heading),
    pitchDegree: Cesium.Math.toDegrees(viewer.camera.pitch),
    rollDegree: Cesium.Math.toDegrees(viewer.camera.roll),
    direction,
    cartesian3,
    transform
  }
  return cameraInfo
}

/**
 * 画点；
 * @param layerId //图层唯一值
 * @param imageUrl //图标
 * @param Degrees //经纬度
 * @param id //唯一值
 */
const addPointGeometryFromDegrees = (layerId, imageUrl, Degrees, id) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  if (findDataSource.length > 0) {
    findDataSource[0].entities.add({
      id: id,
      name: layerId,
      position: Cesium.Cartesian3.fromDegrees(Degrees.lng, Degrees.lat),
      billboard: {
        image: imageUrl,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM
      }
    })
  } else {
    const newDataSource = new Cesium.CustomDataSource(layerId)
    newDataSource.entities.add({
      id: id,
      name: layerId,
      position: Cesium.Cartesian3.fromDegrees(Degrees.lng, Degrees.lat),
      billboard: {
        image: imageUrl,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM
      }
    })
    viewer.dataSources.add(newDataSource)
  }
}

/**
 * 加载闪烁点image；
 * @param layerId //图层唯一值
 * @param imageUrl //图标
 * @param Degrees //经纬度
 * @param id //唯一值
 */
const addSparkleShowPointGeometryFromDegrees = (
  layerId,
  imageUrl,
  Degrees,
  id,
  speed = 1
) => {
  const dx = 0.01 * speed
  let flag = true
  let alpha = 1
  let findDataSource = viewer.dataSources.getByName(layerId)
  if (findDataSource.length <= 0) {
    findDataSource[0] = new Cesium.CustomDataSource(layerId)
    viewer.dataSources.add(findDataSource[0])
  }

  findDataSource[0].entities.add({
    id: id,
    name: layerId,
    position: Cesium.Cartesian3.fromDegrees(Degrees.lng, Degrees.lat),
    billboard: {
      image: imageUrl,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      color: new Cesium.CallbackProperty(function () {
        if (flag) {
          alpha -= dx
          if (alpha <= 0.3) {
            flag = false
          }
        } else {
          alpha += dx
          if (alpha >= 1) {
            flag = true
          }
        }
        return Cesium.Color.YELLOW.withAlpha(alpha)
      }, false),
      // scaleByDistance: new Cesium.NearFarScalar(20000, 1, 100000, 0),
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    }
  })
}

/**
 * 画点；
 * @param cartesian3
 */
const addPointGeometryFromCartesian3 = (cartesian3) => {
  viewer.entities.add({
    position: cartesian3,
    /* billboard: {
       image: flatt3dImg,
       verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
     },*/
    point: {
      color: Cesium.Color.YELLOW,
      pixelSize: 10
    }
  })
}

/**
 * 画线；
 * @param layerId //图层唯一值
 * @param colorStr //颜色值
 * @param Degrees //经纬度坐标集合
 * @param id //唯一值
 */
const addPolylineGeometryFromDegrees = (
  layerId,
  colorStr,
  width,
  Degrees,
  id
) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  if (findDataSource.length > 0) {
    findDataSource[0].entities.add({
      id: id,
      name: layerId,
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray(Degrees),
        width: width,
        material: Cesium.Color.fromCssColorString(colorStr),
        clampToGround: true
      }
    })
  } else {
    const newDataSource = new Cesium.CustomDataSource(layerId)
    newDataSource.entities.add({
      id: id,
      name: layerId,
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray(Degrees),
        width: width,
        material: Cesium.Color.fromCssColorString(colorStr),
        clampToGround: true
      }
    })
    viewer.dataSources.add(newDataSource)
  }
}

/**
 * 加载BIM数据；
 * @param url
 */
const addBIM = (url) => {
  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: url
    })
  )
  tileset.readyPromise
    .then((tileset) => {
      let cartographic = Cesium.Cartographic.fromCartesian(
        tileset.boundingSphere.center
      )
      if (cartographic) {
        viewer.zoomTo(
          tileset,
          new Cesium.HeadingPitchRange(
            0.0,
            -0.5,
            tileset.boundingSphere.radius * 1.0
          )
        )
      }
    })
    .otherwise(function (error) {
      console.log(error)
    })
}

const update3dtilesMaxtrix = ({
  type,
  scale = 1.0,
  longitude = 118.5960711,
  latitude = 30.1570957,
  height = 800, //修改高度
  rx = 0,
  ry = 0,
  rz = 0, //修改旋转
  alpha = 1
}) => {
  const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(rx))
  const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(ry))
  const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rz))
  const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
  const rotationY = Cesium.Matrix4.fromRotationTranslation(my)
  const rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
  //平移 修改经纬度
  const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
  const m = Cesium.Transforms.eastNorthUpToFixedFrame(position)

  //旋转、平移矩阵相乘
  Cesium.Matrix4.multiply(m, rotationX, m)
  Cesium.Matrix4.multiply(m, rotationY, m)
  Cesium.Matrix4.multiply(m, rotationZ, m)
  //缩放 修改缩放比例
  const scaleMatrix = Cesium.Matrix4.fromUniformScale(scale)
  Cesium.Matrix4.multiply(m, scaleMatrix, m)
  //赋值给tileset
  BIM[type]._root.transform = m
  //调整地下透明度
  /*   viewer.scene.globe.translucency.frontFaceAlphaByDistance.nearValue =
    Cesium.Math.clamp(alpha, 0.0, 1.0); */
}
const load3Dtiles = ({
  type,
  url,
  position = [117, 31],
  height = 0,
  rotation = [0, 0, 0],
  scale = 1,
  alpha = 1,
  show = true,
  color = 'white',
  fs = ''
}) => {
  const colorStr = "color('" + color + "')" //不加单引号不识别。
  BIM[type] = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url,
      luminanceAtZenith: 1,
      lightColor: new Cesium.Cartesian3(0.3, 0.3, 0.3)
    })
  )
  BIM[type].readyPromise.then(function (tileset) {
    tileset.enableModelExperimental = true //泛光效果关闭
    tileset.style = new Cesium.Cesium3DTileStyle({
      color: {
        conditions: [['true', colorStr]]
      }
    })
    tileset.show = show
    update3dtilesMaxtrix({
      type,
      scale,
      longitude: position[0], //,
      latitude: position[1], //29.850634,
      height, //修改高度
      rx: rotation[0],
      ry: rotation[1],
      rz: rotation[2], //修改旋转
      alpha
    })
    /*   BIM[type].customShader = new Cesium.CustomShader({
      lightingModel: Cesium.LightingModel.UNLIT,
      fragmentShaderText: fs
    }) */
  })
}
const activeFloor = (floor) => {
  BIM.longhu.show = false
  BIM.floor1.show = false
  BIM.floor2.show = false
  BIM.floor3.show = false
  switch (floor) {
    case 0:
      BIM.longhu.show = true

      break
    case 1:
      BIM.floor1.show = true

      break
    case 2:
      BIM.floor2.show = true

      break
    case 3:
      BIM.floor3.show = true
      break
  }
}

/**
 * 加载3dtile数据；
 * @param url
 * @param colorName 对应颜色值名称
 */
const add3dTile = (url, color = 'Orange', luminance = '8000') => {
  const colorStr = "color('" + color + "')" //不加单引号不识别。
  Cesium.ExperimentalFeatures.enableModelExperimental = true //泛光效果开启
  const city = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      name: 'cityModel',
      url: url,
      maximumScreenSpaceError: 2 //最大的屏幕空间误差
      // maximumNumberOfLoadedTiles: 1000, //最大加载瓦片个数
    })
  )

  city.readyPromise.then(function (tileset) {
    tileset.style = new Cesium.Cesium3DTileStyle({
      color: {
        conditions: [
          [`${color} === 1`, "color('red', 1)"],
          [`${color} === 2`, "color('orange', 1)"],
          [`${color} === 3`, "color('yellow', 1)"],
          [`${color} === 4`, "color('blue', 1)"],
          ['true', colorStr]
        ]
      }
    })
    /*    const fs8000 = `
      void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
				  float _baseHeight = 30.0; // 物体的基础高度，需要修改成一个合适的建筑基础高度
				  float _heightRange = 100.0; // 高亮的范围(_baseHeight ~ _baseHeight + _      heightRange) 默认是 0-60米
				  float _glowRange = 300.0; // 光环的移动范围(高度)
			    float vtxf_height = fsInput.attributes.positionMC.z;
          float vtxf_a13 = fsInput.attributes.positionMC.z * fsInput.attributes.positionMC.z;
          float vtxf_a14 = vtxf_a13 / 8000.0;
			    float vtxf_a11 = fract(czm_frameNumber / 360.0) * 3.14159265 * 2.0;
			    float vtxf_a12 = vtxf_height / _heightRange + sin(vtxf_a11) * 0.1;
          float vtxf_a15 = vtxf_a13 /80000.0;
          material.diffuse*= vec3(vtxf_a14, vtxf_a14, vtxf_a14);
        }
    `
    const fs1000 = `
      void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
				  float _baseHeight = 30.0; // 物体的基础高度，需要修改成一个合适的建筑基础高度
				  float _heightRange = 100.0; // 高亮的范围(_baseHeight ~ _baseHeight + _      heightRange) 默认是 0-60米
				  float _glowRange = 300.0; // 光环的移动范围(高度)
			    float vtxf_height = fsInput.attributes.positionMC.z;
          float vtxf_a13 = fsInput.attributes.positionMC.z * fsInput.attributes.positionMC.z;
          float vtxf_a14 = vtxf_a13 / 1000.0;
			    float vtxf_a11 = fract(czm_frameNumber / 360.0) * 3.14159265 * 2.0;
			    float vtxf_a12 = vtxf_height / _heightRange + sin(vtxf_a11) * 0.1;
          float vtxf_a15 = vtxf_a13 /80000.0;
          material.diffuse*= vec3(vtxf_a14, vtxf_a14, vtxf_a14);
        }
    `

    city.customShader = new Cesium.CustomShader({
      lightingModel: Cesium.LightingModel.UNLIT,
      fragmentShaderText: luminance === '8000' ? fs8000 : fs1000
    }) */
  })
}

/**
 * 加载geojson数据
 * @param data
 * @param type
 * @param layerId
 * @param imageUrl
 */
const loadGeoJson = (data, type, layerId, options) => {
  const { imageUrl, colorStr = '#177fc6', opacity = 0.8, width = 3 } = options
  if (data !== null) {
    const dataPromise = Cesium.GeoJsonDataSource.load(data, {
      clampToGround: true
    })
    dataPromise.then(function (dataSource) {
      viewer.dataSources.add(dataSource)
      dataSource.name = layerId //设置数据源名称
      let entities = dataSource.entities.values
      for (let i = 0, iLen = entities.length, entity; i < iLen; i++) {
        entity = entities[i]
        if (type === 'Point') {
          entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
          entity.billboard.image = imageUrl
        } else if (type === 'LineString') {
          entity.polyline.material =
            Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity)
          entity.polyline.width = width
        } else if (type === 'Polygon') {
          entity.polygon.material =
            Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity)
          entity.polygon.outline = false
          entity.polygon.extrudedHeight = entity.properties.height
        }
      }
    })
  }
}

/**
 * 加载爆炸分析geojson数据
 * @param data
 * @param layerId
 */
const loadBurstBufferGeoJson = (data, layerId) => {
  if (data !== null) {
    const dataPromise = Cesium.GeoJsonDataSource.load(data, {
      clampToGround: true
    })
    dataPromise.then(function (dataSource) {
      viewer.dataSources.add(dataSource)
      dataSource.name = layerId //设置数据源名称
      let entities = dataSource.entities.values
      for (let i = 0, iLen = entities.length, entity; i < iLen; i++) {
        entity = entities[i]
        if (entity._properties._buffer._value === 1) {
          entity.polygon.material =
            Cesium.Color.fromCssColorString('#F43816').withAlpha(0.8)
        } else if (entity._properties._buffer._value === 2) {
          entity.polygon.material =
            Cesium.Color.fromCssColorString('#FFBA00').withAlpha(0.8)
        } else {
          entity.polygon.material =
            Cesium.Color.fromCssColorString('#F7EE16').withAlpha(0.8)
        }
        entity.polygon.outline = false
        entity.polygon.extrudedHeight = entity.properties.height
        entity.show = false
      }
    })
  }
}

/***
 * 周边分析
 **/
const perimeterBufferAnalysis = (center, offset, colorStr, isShow) => {
  clearBurstBufferEntitiesAll()
  addRandomPolygon('BurstBuffer3', center, offset * 5, colorStr, 0.3, isShow)
  addRandomPolygon('BurstBuffer2', center, offset * 2, colorStr, 0.3, isShow)
  addRandomPolygon('BurstBuffer1', center, offset, colorStr, 0.3, isShow)
}

/**
 * 创建随机多边形
 **/
const addRandomPolygon = (
  layerId,
  center,
  offset,
  colorStr,
  opacity = 0.8,
  isShow
) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  findDataSource.forEach((dataSource) => {
    dataSource.show = isShow
  })
  let tmpArray = []
  /* const x0 = center.lng;
   const y0 = center.lat;
   const x1 = center.lng - offset * Math.random() - offset;
   const y1 = center.lat + offset * Math.random() + offset;
   const x2 = center.lng + offset * Math.random() + offset;
   const y2 = center.lat - offset * Math.random() - offset;*/
  tmpArray.push(center.lng - offset * Math.random() - offset)
  tmpArray.push(center.lat + offset * Math.random() + offset)

  tmpArray.push(center.lng)
  tmpArray.push(center.lat + offset * 2)

  tmpArray.push(center.lng + offset * Math.random() + offset)
  tmpArray.push(center.lat + offset * Math.random() + offset)

  tmpArray.push(center.lng + offset * 2)
  tmpArray.push(center.lat)

  tmpArray.push(center.lng + offset * Math.random() + offset)
  tmpArray.push(center.lat - offset * Math.random() - offset)

  tmpArray.push(center.lng)
  tmpArray.push(center.lat - offset * 2)

  tmpArray.push(center.lng - offset * Math.random() - offset)
  tmpArray.push(center.lat - offset * Math.random() - offset)

  tmpArray.push(center.lng - offset * 2)
  tmpArray.push(center.lat)
  const position = Cesium.Cartesian3.fromDegreesArray(tmpArray)
  if (findDataSource.length > 0) {
    findDataSource[0].entities.add({
      name: layerId,
      polygon: {
        hierarchy: position,
        height: 0,
        material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity),
        outline: true,
        outlineWidth: 3,
        outlineColor: Cesium.Color.fromCssColorString(colorStr)
      }
    })
  } else {
    const newDataSource = new Cesium.CustomDataSource(layerId)
    newDataSource.show = isShow
    newDataSource.entities.add({
      name: layerId,
      polygon: {
        hierarchy: position,
        height: 0,
        material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity),
        outline: true,
        outlineWidth: 3,
        outlineColor: Cesium.Color.fromCssColorString(colorStr)
      }
    })
    viewer.dataSources.add(newDataSource)
  }
}

/**
 * 改变缓冲区显示
 * @param layerId
 * @param isShow
 */
const changeDataSourcesShow = (layerId, isShow) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  findDataSource.forEach((dataSource) => {
    dataSource.show = isShow
  })
}

/**
 * 清除缓冲区临时数据
 */
const clearBurstBufferEntitiesAll = () => {
  clearDataSourcesEntitiesByLayerId('BurstBuffer3')
  clearDataSourcesEntitiesByLayerId('BurstBuffer2')
  clearDataSourcesEntitiesByLayerId('BurstBuffer1')
}

/**
 * 清除地图指定图层数据
 */
const clearDataSourcesEntitiesByLayerId = (layerId) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  findDataSource.forEach((dataSource) => {
    dataSource.entities.removeAll()
  })
}

/**
 * 画椭圆
 */
const addEllipse = (
  layerId,
  center,
  maxRadius,
  minRadius,
  angle,
  colorStr,
  opacity = 0.8,
  isShow
) => {
  let findDataSource = viewer.dataSources.getByName(layerId)
  findDataSource.forEach((dataSource) => {
    dataSource.show = isShow
  })
  if (findDataSource.length > 0) {
    findDataSource[0].entities.add({
      name: layerId,
      position: Cesium.Cartesian3.fromDegrees(center.lng, center.lat),
      ellipse: {
        semiMajorAxis: maxRadius,
        semiMinorAxis: minRadius,
        rotation: Cesium.Math.toRadians(-angle), //cesium与turf旋转角相反
        material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity)
      }
    })
  } else {
    const newDataSource = new Cesium.CustomDataSource(layerId)
    newDataSource.show = isShow
    newDataSource.entities.add({
      name: layerId,
      position: Cesium.Cartesian3.fromDegrees(center.lng, center.lat),
      ellipse: {
        semiMajorAxis: maxRadius,
        semiMinorAxis: minRadius,
        rotation: Cesium.Math.toRadians(-angle), //cesium与turf旋转角相反
        material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity)
      }
    })
    viewer.dataSources.add(newDataSource)
  }
}

/**
 * 请求json数据资源
 **/
const fetchJson = (url) => {
  return Cesium.Resource.fetchJson(url)
}

/**
 * 创建turf椭圆
 */
const createTurfEllipse = (center, maxRadius, minRadius, angle) => {
  return turf.ellipse(
    [center.lng, center.lat],
    maxRadius / 1000, //单位千米
    minRadius / 1000, //单位千米
    {
      angle: angle
    }
  )
}

/**
 *多边形切割线
 */
const splitLineString = (lineString, splitter) => {
  console.log(lineString)
  const splitIn = []
  const splitOut = []
  const features = lineString.features
  for (let i = 0; i < features.length; i++) {
    const feature = features[i]
    const cross = turf.booleanCrosses(feature, splitter)
    if (!cross) {
      const contain = turf.booleanContains(splitter, feature)
      if (contain) {
        splitIn.push(feature)
      } else {
        splitOut.push(feature)
      }
    } else {
      const result = turf.lineSplit(feature, splitter)
      const resultFeatures = result.features
      resultFeatures.forEach((feature) => {
        const boolean = turf.booleanContains(splitter, feature)
        if (boolean) {
          splitIn.push(feature)
        } else {
          splitOut.push(feature)
        }
      })
    }
  }
  const OutFeatureCollection = {
    type: 'FeatureCollection',
    features: splitOut
  }
  const InFeatureCollection = {
    type: 'FeatureCollection',
    features: splitIn
  }
  const result = {
    In: InFeatureCollection,
    Out: OutFeatureCollection
  }
  return result
}

/**
 * 导入闪烁线；
 * @param jsonUrl
 * @param layerId //图层唯一值
 * @param colorStr //颜色值
 * @param width //线宽
 */
/* const loadPolylineGeometryFromGeojson = (
  layerId,
  jsonUrl,
  colorStr,
  width = 4,
  isShow
) => {
  if (jsonUrl !== null) {
    const dataPromise = Cesium.GeoJsonDataSource.load(jsonUrl, {
      clampToGround: true
    })
    dataPromise.then(function (dataSource) {
      viewer.dataSources.add(dataSource)
      dataSource.show = isShow
      dataSource.name = layerId //设置数据源名称
      let entities = dataSource.entities.values
      for (let i = 0, iLen = entities.length, entity; i < iLen; i++) {
        entity = entities[i]
        entity.polyline.width.setValue(width)
        entity.polyline.material = new Cesium.LineFlickerMaterialProperty({
          speed: 15, //设置随机变化速度
          color: Cesium.Color.fromCssColorString(colorStr).withAlpha(0.9)
        })
      }
    })
  }
} */

/**
 * 放大
 */
const zoomIn = () => {
  let position = viewer.camera.position
  let cameraHeight =
    viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height
  // 每次缩小 20 倍，参数可改
  let moveRate = cameraHeight / 2.5
  viewer.camera.moveForward(moveRate)
}

/**
 * 缩小
 */
const zoomOut = () => {
  let position = viewer.camera.position
  let cameraHeight =
    viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height
  // 每次缩小 20 倍，参数可改
  let moveRate = cameraHeight / 2.5
  viewer.camera.moveBackward(moveRate)
}

/**
 * 复位到指定位置
 */
const zoomReset = (lng, lat, height = 1000) => {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(lng, lat, height)
  })
}

/**
 * 注册鼠标左键事件，点击实体对象，触发相关事件
 */
const eventLeftClick = () => {
  handler.setInputAction(function (movement) {
    const hightDataSource = viewer.dataSources.getByName('heightLightLayer')
    if (hightDataSource.length > 0) {
      hightDataSource[0].entities.removeAll()
    }
    const pickedFeature = viewer.scene.pick(movement.position)
    if (!Cesium.defined(pickedFeature)) {
      // nothing picked
    } else if (
      Cesium.defined(pickedFeature) &&
      Cesium.defined(pickedFeature.id)
    ) {
      if (pickedFeature.id instanceof Cesium.Entity) {
        console.log('pickedFeature1:', pickedFeature)
        emits('openPopupBox', pickedFeature.id)
        hightDataSource[0].entities.add({
          id: pickedFeature.id.id,
          name: 'heightLightLayer',
          position: pickedFeature.id.position,
          ellipse: {
            semiMinorAxis: 8.0,
            semiMajorAxis: 8.0,
            material: Cesium.Color.fromCssColorString('#00FFFF')
          }
        })
      } else if (pickedFeature.primitive instanceof Cesium.Billboard) {
        console.log('pickedFeature2:', pickedFeature)
        const pickArray = viewer.scene.drillPick(movement.position, 2)
        emits('openPopupBox', pickArray[1].id)
        hightDataSource[0].entities.add({
          id: pickArray[1].id.id,
          name: 'heightLightLayer',
          position: pickArray[1].id.position,
          ellipse: {
            semiMinorAxis: 8.0,
            semiMajorAxis: 8.0,
            material: Cesium.Color.fromCssColorString('#00FFFF')
          }
        })
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

/**
 * 弹框
 * @param offset
 * @param entity
 * @param popupTemplate
 * @param popupBoxProps
 * @param isFly
 */
const showInfoWindow = ({
  offset,
  entity,
  popupTemplate,
  popupBoxProps = {},
  isFly = true
}) => {
  viewer.entities.removeAll()
  const { data = [], title } = popupBoxProps
  if (!offset) {
    offset = {
      x: 0,
      y: 50
    }
  }
  let center = [0, 0]
  if (entity.position) {
    const point = entity.position._value
    center = cartesian3ToDegree(point)
  } else {
    center = [entity.longitude, entity.latitude]
  }
  if (isFly) {
    flyToPosition(center[0], center[1])
  }
  if (entity) {
    const containerEle = document.getElementById(viewer.container.id)
    const wrapperEle = document.createElement('div')
    wrapperEle.style.display = 'none'
    const vueTempCom = createApp({
      render: () => {
        const onClose = () => {
          viewer.entities.removeAll()
          const hightDataSource =
            viewer.dataSources.getByName('heightLightLayer')
          if (hightDataSource.length > 0) {
            hightDataSource[0].entities.removeAll()
          }
          containerEle.childElementCount > 1 &&
            containerEle.removeChild(wrapperEle)
        }
        return h(popupTemplate, {
          title: title,
          data: data,
          echarts: echarts,
          // showBIM: compProps.showBIM,
          onClick: ($event) => {
            if (
              $event.target &&
              $event.target.childNodes.length > 0 &&
              $event.target.childNodes[0].nodeValue === '×'
            ) {
              onClose()
            }
          }
        })
      }
    })
      .use(ElementPlus, { locale })
      .directive('echartResize', {
        mounted(el) {
          bind(el)
        },
        unmounted(el) {
          unbind(el)
        }
      })
    /* installIcons(vueTempCom)*/
    vueTempCom.mount(wrapperEle)
    containerEle.appendChild(wrapperEle)
    if (containerEle.childElementCount === 3) {
      const node = containerEle.children[1]
      containerEle.removeChild(node)
    }
    viewer.scene.postRender.addEventListener(() => {
      if (!entity.position) {
        entity.position = {
          _value: Cesium.Cartesian3.fromDegrees(
            entity.longitude,
            entity.latitude
          )
        }
      }
      const px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
        viewer.scene,
        entity.position._value
      )
      if (!px) return
      wrapperEle.style.left =
        px.x - offset.x - Math.ceil(wrapperEle.offsetWidth / 2) + 6 + 'px'
      wrapperEle.style.top =
        px.y - offset.y - Math.ceil(wrapperEle.offsetHeight) + 'px'
      wrapperEle.style.position = 'fixed'
      setTimeout(function () {
        wrapperEle.style.display = 'block'
      }, 50)
      //解决滚动不隐藏问题
      /*  const camerPosition = viewer.camera.position;
        let viewHeight = viewer.scene.globe.ellipsoid.cartesianToCartographic(camerPosition).height;
        viewHeight += viewer.scene.globe.ellipsoid.maximumRadius;
        if ((!(Cesium.Cartesian3.distance(camerPosition, px) > viewHeight)) && viewer.camera.positionCartographic.height < 50000000) {
          wrapperEle.style.display = "block";
        } else {
          wrapperEle.style.display = "none";
        }*/
    })
  }
}

/**
 * 关闭弹窗
 **/
const closeInfoWindow = () => {
  const containerEle = document.getElementById(viewer.container.id)
  if (
    containerEle.childElementCount === 3 ||
    containerEle.childElementCount === 2
  ) {
    const node = containerEle.children[1]
    containerEle.removeChild(node)
  }
}

const addMarker = ({
  name = '标记点',
  description = 'description',
  image = '',
  width = 20,
  height = 20,
  colorStr = '#e5a935',
  size = 20,
  show = true
}) => {
  clearHandler()

  function drawMarker({
    position,
    type,
    image,
    width = billboardStyle.width,
    height = billboardStyle.height,
    name = '标记点',
    description = 'description',
    colorStr = '#e5a935',
    size = billboardStyle.width,
    show = true
  }) {
    const color = Cesium.Color.fromCssColorString(colorStr)
    if (!Cesium.defined(datasource[type])) {
      datasource[type] = new Cesium.CustomDataSource(type)
      viewer.dataSources.add(datasource[type])

      flag[type] = true
      addedLayers.push(type) // collect the addedLayers for clear all entities once.
    }
    datasource[type].entities.add({
      position: Cesium.Cartesian3.fromDegrees(position[0], position[1]),
      billboard: {
        image,
        width,
        height,
        color,
        pixelOffset: new Cesium.Cartesian2(width / 2, -height / 2),
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
      },
      label: {
        text: name,
        font: size + 'pt monospace',
        scale: 0.5,
        // scaleByDistance: new Cesium.NearFarScalar(1.0e2, 1.5, 1.5e6, 0.5),
        fillColor: color, // 填充颜色
        // outlineColor: color, //边颜色
        style: Cesium.LabelStyle.FILL, //FILL_AND_OUTLINE,
        // outlineWidth: 0.5,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
        pixelOffset: new Cesium.Cartesian2(0, 18), // 偏移量
        // distanceDisplayCondition: distanceDisplayCondition,
        show
      },
      properties: {
        description
      }
    })
  }

  handler.setInputAction(function (click) {
    const degree = cartesian2ToDegree(click.position)
    drawMarker({
      position: degree,
      type: 'marker',
      image,
      width: size,
      height: (size * height) / width,
      name,
      description,
      colorStr,
      size,
      show
    })
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  flag.marker = true
  showPoints('marker')
  handler.setInputAction(function () {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    eventLeftClick()
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
  handler.setInputAction(function () {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    eventLeftClick()
  }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
}

const removeMarker = () => {
  if (Cesium.defined(handler.removeInputAction)) {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    eventLeftClick()
  }
  if (Cesium.defined(datasource.marker)) {
    datasource.marker.entities.removeAll()
  }
}
const removeMeasures = () => {
  for (let i = 0; i < measures.length; i++) {
    measures[i].unRegisterEvents()
    measures[i].clear()
  }
}

const measureLine = () => {
  clearHandler()
  const measure = new MeasureDistance(viewer)
  measure.activate()
  measures.push(measure)
}

const clearHandler = () => {
  if (Cesium.defined(handler.removeInputAction)) {
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }
}

const clearScreen = () => {
  removeMarker()
  removeMeasures()
  viewer.entities.removeAll()
  const hightDataSource = viewer.dataSources.getByName('heightLightLayer')
  if (hightDataSource.length > 0) {
    hightDataSource[0].entities.removeAll()
  }
  eventLeftClick()
}

const findLightingFlyToPosition = (layerId, id, point) => {
  const hightDataSource = viewer.dataSources.getByName('heightLightLayer')
  const findDataSource = viewer.dataSources.getByName(layerId)
  let selectEntity = {}
  if (hightDataSource.length > 0) {
    hightDataSource[0].entities.removeAll()
  }
  if (findDataSource.length > 0) {
    selectEntity = findDataSource[0].entities.getById(id)
    if (selectEntity && selectEntity.id) {
      hightDataSource[0].entities.add({
        id: selectEntity.id,
        name: 'heightLightLayer',
        position: Cesium.Cartesian3.fromDegrees(point[0], point[1]),
        ellipse: {
          semiMinorAxis: 8.0,
          semiMajorAxis: 8.0,
          material: Cesium.Color.fromCssColorString('#00FFFF') //Cesium.Color.fromCssColorString('#00FFFF')
        }
      })
    }
  }
  flyToPosition(point[0], point[1])
}

const showPointHeightLightLayer = (
  point,
  size = 8,
  colorStr = '#00FFFF',
  opacity = 1
) => {
  const hightDataSource = viewer.dataSources.getByName('heightLightLayer')
  if (hightDataSource.length > 0) {
    hightDataSource[0].entities.removeAll()
  }
  hightDataSource[0].entities.add({
    name: 'heightLightLayer',
    position: Cesium.Cartesian3.fromDegrees(point[0], point[1]),
    ellipse: {
      semiMinorAxis: size,
      semiMajorAxis: size,
      material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity)
    }
  })
}

const showPolylineHeightLightLayer = (
  Degrees,
  width = 4,
  colorStr = '#00FFFF',
  opacity = 1
) => {
  const hightDataSource = viewer.dataSources.getByName('heightLightLayer')
  if (hightDataSource.length > 0) {
    hightDataSource[0].entities.removeAll()
  }
  hightDataSource[0].entities.add({
    name: 'heightLightLayer',
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray(Degrees),
      material: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity),
      width: width
    }
  })
}

/**
 * 地图打点获取坐标信息
 * @description: 获取当前鼠标点击位置坐标，并添加到图上显示
 * @return {*}
 */
const getClickPointToMap = () => {
  // 注册屏幕点击事件
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  handler.setInputAction(function (event) {
    // 转换为不包含地形的笛卡尔坐标
    let clickPosition = viewer.scene.camera.pickEllipsoid(event.position)
    // 添加点
    viewer.entities.add({
      position: clickPosition,
      point: {
        color: Cesium.Color.CYAN,
        pixelSize: 10
      }
    })
    // 转经纬度（弧度）坐标
    let radiansPos = Cesium.Cartographic.fromCartesian(clickPosition)
    // 转角度
    // console.log("经度：" + Cesium.Math.toDegrees(radiansPos.longitude) + ", 纬度：" + Cesium.Math.toDegrees(radiansPos.latitude));
    let clickPoint = {
      longitude: Cesium.Math.toDegrees(radiansPos.longitude),
      latitude: Cesium.Math.toDegrees(radiansPos.latitude)
    }
    emits('getClickPoint', clickPoint)
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

const addLightEffect = (
  lng,
  lat,
  height,
  intensity = 1,
  colorStr = '#00FFFF',
  opacity = 1
) => {
  viewer.scene.light = new Cesium.DirectionalLight({
    direction: Cesium.Cartesian3.fromDegrees(lng, lat, height),
    color: Cesium.Color.fromCssColorString(colorStr).withAlpha(opacity),
    intensity: intensity
  })
}

/**
 * 动态光效预警
 * @param imgUrl
 */
const showLightEffect = (imgUrl, matUrl) => {
  viewer.scene.globe.depthTestAgainstTerrain = true //开启或关闭地形遮盖
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  handler.setInputAction(function (event) {
    let r1 = 20
    let r2 = 20
    let height = 0
    let position = viewer.scene.pickPosition(event.position)
    if (Cesium.defined(position)) {
      const cartographic = Cesium.Cartographic.fromCartesian(position)
      height = cartographic.height.toFixed(2) + 100
    }
    viewer.entities.removeById('lightEffect')
    // 添加点
    viewer.entities.add({
      id: 'lightEffect',
      position: position,
      billboard: {
        image: imgUrl,
        width: 26,
        height: 34,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM
      },
      ellipse: {
        semiMinorAxis: new Cesium.CallbackProperty(function () {
          r1 = r1 + 0.5
          if (r1 >= 50) {
            r1 = 0
          }
          return r1
        }, false),
        semiMajorAxis: new Cesium.CallbackProperty(function () {
          r2 = r2 + 0.5
          if (r2 >= 50) {
            r2 = 0
          }
          return r2
        }, false),
        // material: Cesium.Color.RED.withAlpha(0.3),
        material: new Cesium.ImageMaterialProperty({
          image: matUrl,
          repeat: new Cesium.Cartesian2(1.0, 1.0),
          transparent: true,
          color: Cesium.Color.WHITE.withAlpha(1)
        }),
        height: height
      }
    })
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

/**
 * 清除圆扩散特效
 */
const clearPostProcessStages = () => {
  viewer.scene.postProcessStages.removeAll()
}
/**
 * 空间距离测量
 */
const drawLineMeasure = () => {
  clearHandler()
  if (!handleMeasure) {
    handleMeasure = new MeasureTools(viewer)
  }
  handleMeasure.drawLineMeasureGraphics({
    clampToGround: true,
    callback: () => {}
  })
}
/**
 * 空间面积测量
 */
const drawAreaMeasure = () => {
  clearHandler()
  if (!handleMeasure) {
    handleMeasure = new MeasureTools(viewer)
  }
  handleMeasure.drawAreaMeasureGraphics({
    clampToGround: true,
    callback: () => {}
  })
}
/**
 * 三维量测
 */
const drawTriangles3DMeasure = () => {
  clearHandler()
  if (!handleMeasure) {
    handleMeasure = new MeasureTools(viewer)
  }
  handleMeasure.drawTrianglesMeasureGraphics({
    callback: () => {}
  })
}
/**
 * 清除测量
 */
const clearDrawMeasure = () => {
  if (!handleMeasure) {
    handleMeasure = new MeasureTools(viewer)
  }
  handleMeasure.clearDrawMeasureGraphics()
}

const bufferAnimation = () => {
  bufferEntity &&
    bufferEntity.forEach((entity) => {
      entity.animation = !entity.animation
    })
}

/**
 * @description: 产生随机点
 * @param {*} position：中心点坐标
 * @param {*} num：随机点数量
 * @return {*}
 */
const generateRandomPosition = (position, num) => {
  let list = []
  for (let i = 0; i < num; i++) {
    // random产生的随机数范围是0-1，需要加上正负模拟
    let lon = position[0] + Math.random() * 0.4 * (i % 2 === 0 ? 1 : -1)
    let lat = position[1] + Math.random() * 0.4 * (i % 2 === 0 ? 1 : -1)
    list.push([lon, lat])
  }
  return list
}

/**
 * @description: 抛物线构造函数
 * @param {*}
 * @return {*}
 */
const parabola = (startPosition, endPosition, height = 0, count = 50) => {
  //方程 y=-(4h/L^2)*x^2+h h:顶点高度 L：横纵间距较大者
  let result = []
  height = Math.max(+height, 100)
  count = Math.max(+count, 50)
  let diffLon = Math.abs(startPosition[0] - endPosition[0])
  let diffLat = Math.abs(startPosition[1] - endPosition[1])
  let L = Math.max(diffLon, diffLat)
  let dlt = L / count
  if (diffLon > diffLat) {
    //base on lon
    let delLat = (endPosition[1] - startPosition[1]) / count
    if (startPosition[0] - endPosition[0] > 0) {
      dlt = -dlt
    }
    for (let i = 0; i < count; i++) {
      let h =
        height -
        (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
          Math.pow(L, 2)
      let lon = startPosition[0] + dlt * i
      let lat = startPosition[1] + delLat * i
      let point = Cesium.Cartesian3.fromDegrees(lon, lat, h)
      result.push(point)
    }
  } else {
    //base on lat
    let delLon = (endPosition[0] - startPosition[0]) / count
    if (startPosition[1] - endPosition[1] > 0) {
      dlt = -dlt
    }
    for (let i = 0; i < count; i++) {
      let h =
        height -
        (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
          Math.pow(L, 2)
      let lon = startPosition[0] + delLon * i
      let lat = startPosition[1] + dlt * i
      let point = Cesium.Cartesian3.fromDegrees(lon, lat, h)
      result.push(point)
    }
  }
  return result
}

/**
 * 淹没分析函数，通过拉伸面的高度来进行分析
 * @param {*} viewer
 * @param {*} targertWaterHeight ：目标水位高度
 * @param {*} positions ：研究区域底部坐标数组
 * @param {*} waterHeight ：当前水位高度
 * @param {*} speed ：水位上涨速度
 */
const inundationAnalysis = (
  positions,
  targertWaterHeight,
  waterHeight,
  speed
) => {
  viewer.scene.globe.depthTestAgainstTerrain = true //开启或关闭地形遮盖
  viewer.entities.add({
    polygon: {
      hierarchy: new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray(positions)
      ),
      perPositionHeight: true,
      // 使用回调函数Callback，直接设置extrudedHeight会导致闪烁
      extrudedHeight: new Cesium.CallbackProperty(function () {
        waterHeight += speed
        if (waterHeight > targertWaterHeight) {
          waterHeight = targertWaterHeight
        }
        return waterHeight
      }, false),
      material: Cesium.Color.fromBytes(64, 157, 253, 150)
    }
  })
}

/**
 * @description: 日照阴影效果模拟
 * @param {*} speed：变化速率
 * @return {*}
 */
const lightingShadowAnalysis = (speed) => {
  viewer.scene.globe.enableLighting = true
  viewer.shadows = true
  viewer.clock.multiplier = speed
}

/* const viewShedAnalysis = (options) => {
  viewer.scene.globe.depthTestAgainstTerrain = true //开启或关闭地形遮盖
  const opt = {
    ...options,
    viewPosition:
      options.viewPosition && options.viewPosition.length > 0
        ? Cesium.Cartesian3.fromDegrees(
            options.viewPosition[0],
            options.viewPosition[1],
            options.viewPosition[2]
          )
        : options.viewPosition,
    viewPositionEnd:
      options.viewPositionEnd && options.viewPositionEnd.length > 0
        ? Cesium.Cartesian3.fromDegrees(
            options.viewPositionEnd[0],
            options.viewPositionEnd[1],
            options.viewPositionEnd[2]
          )
        : options.viewPositionEnd
  }
  const viewShed = new ViewShed(viewer, opt)
} */

/**
 * 通视分析
 */
/* const viewVisibilityAnalysis = () => {
  viewer.scene.globe.depthTestAgainstTerrain = true
  if (VA && VA.resultPolylines) {
    VA.resultPolylines.forEach((e) => {
      viewer.entities.remove(e)
    })
    VA_positions = []
    viewer.entities.removeById('startPoint')
    viewer.entities.removeById('endPoint')
  }
  VA_handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  VA_handler.setInputAction(function (e) {
    let position = viewer.scene.pickPosition(e.position)
    VA_positions.push(position)
    if (VA_positions.length === 1) {
      viewer.entities.add({
        id: 'startPoint',
        position: position,
        point: {
          color: Cesium.Color.YELLOW,
          pixelSize: 10
        },
        label: {
          text: '观察点',
          font: '16px monospace',
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(-20, -40) //left top
        }
      })
    } else if (VA_positions.length === 2) {
      viewer.entities.add({
        id: 'endPoint',
        position: position,
        point: {
          color: Cesium.Color.CYAN,
          pixelSize: 10
        },
        label: {
          text: '目标点',
          font: '16px monospace',
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(-20, -40) //left top
        }
      })
      va_analysis()
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

  const va_analysis = () => {
    VA_handler.destroy()
    VA = new VisibilityAnalysis(viewer)
    VA.setPositions(VA_positions[0], VA_positions[1])
    VA.useOffsetHeight(0.5)
    VA.startAnalysis()
  }
} */

/**
 * 给实体贴模图片
 */
/*const addImage = (url) => {
  const dataPromise = Cesium.GeoJsonDataSource.load(imgXUrl, {
    clampToGround: true,
  });
  dataPromise.then(function (dataSource) {
    viewer.dataSources.add(dataSource);
    dataSource.name = "layerId"; //设置数据源名称
    let entities = dataSource.entities.values;
    for (let i = 0, iLen = entities.length, entity; i < iLen; i++) {
      entity = entities[i];
      entity.polygon.material = new Cesium.ImageMaterialProperty({
        image: trend1,
        repeat: new Cesium.Cartesian2(1.0, 1.0),
        transparent: true,
      });
      entity.polygon.outline = false;
      viewer.dataSources.raiseToTop(dataSource);

      setTimeout(() => {
        entity.polygon.material = new Cesium.ImageMaterialProperty({
          image: trend2,
          repeat: new Cesium.Cartesian2(1.0, 1.0),
          transparent: true,
        });
        setTimeout(() => {
          entity.polygon.material = new Cesium.ImageMaterialProperty({
            image: trend3,
            repeat: new Cesium.Cartesian2(1.0, 1.0),
            transparent: true,
          });
          setTimeout(() => {
            entity.polygon.material = new Cesium.ImageMaterialProperty({
              image: trend4,
              repeat: new Cesium.Cartesian2(1.0, 1.0),
              transparent: true,
            });
            setTimeout(() => {
              entity.polygon.material = new Cesium.ImageMaterialProperty({
                image: trend5,
                repeat: new Cesium.Cartesian2(1.0, 1.0),
                transparent: true,
              });
            }, 1000)
          }, 1000)
        }, 1000)
      }, 1000)
    }
  });
}*/

/**
 * @description: 画点（primitive billboard)
 * @return {type}
 */
const addBillboard = ({
  type,
  image,
  position,
  id = {},
  width = billboardStyle.width,
  height = billboardStyle.height,
  offset = [0, 0]
}) => {
  if (!Cesium.defined(billboards[type])) {
    billboards[type] = viewer.scene.primitives.add(
      new Cesium.BillboardCollection()
    )
    if (!primitiveName.includes(type)) {
      primitiveName.push(type)
    }
  }

  billboards[type].add({
    image,
    position: Cesium.Cartesian3.fromDegrees(position[0], position[1]),
    id,
    width,
    height,
    pixelOffset: new Cesium.Cartesian2(0 + offset[0], -height / 2 + offset[1]),
    // VerticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    // HorizontalOrigin: Cesium.HorizontalOrigin.CENTER,
    // disableDepthTestDistance: 0,
    disableDepthTestDistance: Number.POSITIVE_INFINITY,
    // HeightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    // HeightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    eyeOffset: new Cesium.Cartesian3(0, 0, -1)
  })
}
const labelName = []
const addLabel = ({
  type,
  text,
  position,
  fillColor = Cesium.Color.YELLOW,
  outlineColor = Cesium.Color.YELLOW,
  pixelOffset = new Cesium.Cartesian2(-9, -9),
  distanceDisplayCondition = new Cesium.DistanceDisplayCondition(
    0,
    Number.MAX_VALUE
  ),
  show = true
}) => {
  if (!Cesium.defined(labels[type])) {
    labels[type] = viewer.scene.primitives.add(new Cesium.LabelCollection())
  }
  if (!labelName.includes(type)) {
    labelName.push(type)
  }
  labels[type].add({
    text: text,
    font: '18pt monospace',
    scale: 0.5,
    position: Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      position[2]
    ),
    fillColor, // 填充颜色
    outlineColor, //边颜色
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 0.5,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
    pixelOffset, // 偏移量
    distanceDisplayCondition,
    disableDepthTestDistance: Number.POSITIVE_INFINITY,
    show
  })
}

/**
 * @description: 为了每个楼层的报警器显示临时写的函数，
 * @param {type} IDArray：某个楼层含有的设备IDs['deviceno1','deviceno2']
 * @param {type} show：是否显示
 * @return {type}
 * @author: Dadaoshen
 */
const showBillboard = ({ IDArray, show = true }) => {
  primitiveName.forEach((type) => {
    const length = billboards[type].length
    for (let i = 0; i < length; i++) {
      const billboard = billboards[type].get(i)
      if (IDArray.includes(billboard.id)) {
        billboard.show = show
      }
    }
  })
}

/**
 * @description:创建动态光墙@longqun
 * @param {type:aray} degrees:坐标 [118,32,117,31]
 * @param {type:url} image：墙壁图片
 * @param {type:``} source：glsl代码
 * @param {type:num} height：墙壁高度 option=100
 * @param {type:string} rgba：颜色 option="rgba(255, 0, 0, 1)"，
 * @param {type:num} speed：光效速度 option=1
 * @return {type}
 */
const createWall = ({
  degrees,
  image,
  source,
  height = 100,
  rgba = 'rgba(255, 0, 0, 1)',
  speed = 1
}) => {
  const wallInstance = new Cesium.GeometryInstance({
    geometry: Cesium.WallGeometry.fromConstantHeights({
      positions: Cesium.Cartesian3.fromDegreesArray(degrees),
      maximumHeight: height,
      vertexFormat: Cesium.MaterialAppearance.VERTEX_FORMAT
    })
  })
  const color = new Cesium.Color.FromCssColorString(rgba)
  const material = new Cesium.Material({
    fabric: {
      type: 'glowWall',
      uniforms: {
        color,
        image,
        speed
      },
      source
    },
    translucent: function () {
      return true
    }
  })

  viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [wallInstance],
      appearance: new Cesium.MaterialAppearance({ material: material })
    })
  )
}
const addedEntities = []
const materialProperty1 = new Cesium.PolylineGlowMaterialProperty({
  // color: new Cesium.Color(14, 257, 243, 1),
  // color: new Cesium.Color(0, 255, 255, 1),
  color: Cesium.Color.AQUA.withAlpha(1),
  glowPower: 0.5
})
const loadEntitiesPolyline = ({ type, url, outlineWidth = 5 }) => {
  Cesium.GeoJsonDataSource.load(url, {
    stroke: Cesium.Color.YELLOW,
    strokeWidth: outlineWidth
    // fill: Cesium.Color.YELLOW.withAlpha(0),
    // clampToGround: true,
  }).then(function (dataSource) {
    datasource[type] = dataSource
    dataSource.name = type
    viewer.dataSources.add(dataSource)
    // flag[type] = true;
    addedEntities.push(type)
    const entities = dataSource.entities.values

    entities.forEach((item) => {
      item.polyline.width = outlineWidth * 2
      item.polyline.material = materialProperty1
    })

    // dataSource.show = true;
    // return promise;
  })
}

const loadEntitiesPolyline2 = ({ type, url, outlineWidth = 2 }) => {
  Cesium.GeoJsonDataSource.load(url, {
    // stroke: Cesium.Color.YELLOW,
    strokeWidth: outlineWidth
    // fill: Cesium.Color.YELLOW.withAlpha(0),
    // clampToGround: true,
  }).then(function (dataSource) {
    datasource[type] = dataSource
    dataSource.name = type
    viewer.dataSources.add(dataSource)
    // flag[type] = true;
    addedEntities.push(type)
    const entities = dataSource.entities.values
    // console.log(entities.length)
    entities.forEach((item) => {
      // item.polyline.width = outlineWidth * 4;
      item.polyline.material = new Cesium.Color(
        96 / 255,
        194 / 255,
        220 / 255,
        0.5
      )
    })
  })
}

const createRandomPoints = ({
  length,
  jsonData,
  bbox = [118.788362, 31.903846, 118.862402, 31.954959],
  minValue = 50,
  maxValue = 100
}) => {
  const heatPoints = []
  for (let i = 0; i < length; i++) {
    let isPointInPolygon = false
    let heatPoint = {}
    while (!isPointInPolygon) {
      const x = bbox[0] + Math.random() * (bbox[2] - bbox[0])
      const y = bbox[1] + Math.random() * (bbox[3] - bbox[1])
      const value = minValue + Math.random() * maxValue
      heatPoint = { x, y, value }
      const point = turf.point([x, y])
      isPointInPolygon = turf.booleanPointInPolygon(point, jsonData)
    }
    heatPoints.push(heatPoint)
  }
  return heatPoints
}
const heatmap = {}
const addHeatmap = async ({ type }) => {
  if (Cesium.defined(heatmap[type])) {
    heatmap[type].show()
  } else {
    const CesiumHeat = getCesiumHeat(Cesium)
    heatmap[type] = new CesiumHeat(
      viewer,
      // data list, each has x, y, and value | 数据数组，每个包含 x,y,value字段
      {
        autoMaxMin: true, // 自动计算最大值和最小值
        min: 0, // 指定最小值，autoMaxMin时无效，非autoMaxMin时必填
        max: 100, // 指定最大值，autoMaxMin时无效，非autoMaxMin时必填
        data: []
      },
      // bbox for heatmap | 只在范围内显示热力图拉近会清晰些，不填默认整个地球但拉近后巨模糊

      [118.788362, 31.903846, 118.862402, 31.954959],
      // heatmap.js construction | heatmap.js的构造配置，不填默认如下，参考 https://www.patrick-wied.at/static/heatmapjs/docs.html
      {},
      // auto radius change with height | 自动按高度控制热点的辐射，默认值如下
      {
        enabled: true, // 是否开启，关闭的话不会自动更新
        min: 6375000, // 最低高度，对应高度的辐射为minRadius
        max: 30000000, // 最大高度，对应高度的辐射为maxRadius
        maxRadius: 10 * 2,
        minRadius: 2 * 2
      },
      // auto resize canvas | 自动按bbox形状控制canvas形状，默认值如下，canvas面积越大越清晰，也越卡
      {
        autoResize: true, // 是否自动调整canvas
        totalArea: 360 * 720, // 总面积，如果自动，必填，如果不自动，无效
        width: 720 * 2, // canvas宽度，如果不自动，必填，如果自动，无效
        height: 360 * 2 // canvas高度，如果不自动，必填，如果自动，无效
      }
    )
    // 动态增加数据（多个）
    const jsonData = await fetchJson('/GisData/json/heatmap.json')
    const heatPoints = createRandomPoints({
      length: 400,
      jsonData: jsonData.features[0]
    })

    // 数据数组
    heatmap[type].addData(heatPoints)
  }
}

const addFlashingBillboard = ({
  type,
  image,
  position,
  id,
  // width = billboardStyle.width,
  // height = billboardStyle.height,
  flashingSpeed = 1,
  properties = {}
}) => {
  startTimeline({
    duration: 4,
    clockRange: Cesium.ClockRange.LOOP_STOP,
    multiplier: 1
  })
  let alpha = 1
  if (!Cesium.defined(datasource[type])) {
    datasource[type] = new Cesium.CustomDataSource(type)
    viewer.dataSources.add(datasource[type])
    flag[type] = true
    addedLayers.push(type) // collect the addedLayers for clear all entities once.
  }
  datasource[type].entities.add({
    id: id,
    name: type,
    position: Cesium.Cartesian3.fromDegrees(position[0], position[1]),
    billboard: {
      image: image,
      // width,
      // height,
      // pixelOffset: new Cesium.Cartesian2(0, -height / 2),

      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      // horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      color: new Cesium.CallbackProperty(function (time) {
        /*      if (flashingFlag) {
          alpha -= dx
          if (alpha <= 0.3) {
            flashingFlag = false
          }
        } else {
          alpha += dx
          if (alpha >= 1) {
            flashingFlag = true
          }
        } */
        // let int = parseInt(time.secondsOfDay)

        alpha =
          time.secondsOfDay % 1 < 0.5
            ? 1.9 * (time.secondsOfDay % 1)
            : 1.9 * (1 - (time.secondsOfDay % 1))

        return Cesium.Color.WHITE.withAlpha(alpha)
      }, false),
      disableDepthTestDistance: Number.POSITIVE_INFINITY
      // heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    }
    // properties
  })
}

const showBillboardEntity = ({ IDArray, show = true }) => {
  addedLayers.forEach((type) => {
    const entities = datasource[type].entities.values
    const length = entities.length
    for (let i = 0; i < length; i++) {
      const entity = entities[i]
      if (IDArray.includes(entity.id)) {
        entity.show = show
      }
    }
  })
}

const test = () => {
  console.log('BIM:', BIM)
  /*  for (let tileset in BIM) {
    console.log('tileset.featureIdLabel:', tileset)
  } */
}
const showPrimitivesAll = (type, show = true) => {
  if (Cesium.defined(points[type])) {
    points[type].show = show
  }
  if (Cesium.defined(billboards[type])) {
    billboards[type].show = show
  }
  if (Cesium.defined(labels[type])) {
    labels[type].show = show
  }
  if (Cesium.defined(polygons[type])) {
    polygons[type].show = show
  }
  if (Cesium.defined(polylines[type])) {
    polylines[type].show = show
  }
}
const clearAddedEntities = () => {
  for (let i = 0; i < addedLayers.length; i++) {
    const layer = addedLayers[i]
    showPoints(layer, false)
  }
}
const clearHeatmap = ({ type }) => {
  if (Cesium.defined(heatmap[type])) {
    heatmap[type].hidden()
  }
}
/* const clearAddedMaps = () => {
  for (const name in addedMaps) {
    addedMaps[name].show = false;
  }
  for (const type in heatmap) {
    heatmap[type].hidden();
  }
}; */
const clearPrimitivesName = () => {
  // setTreeNodesCheck()
  viewer.entities && viewer.entities.removeAll() //use entites for callback property ,time-related
  primitiveName.forEach((item) => {
    showPrimitivesAll(item, false)
  })
}
const startTimeline = ({
  duration = 4, // 4days
  clockRange = Cesium.ClockRange.UNBOUNDED, //always
  multiplier = 1 //speed=1
}) => {
  const timeStart = Cesium.JulianDate.fromDate(new Date())
  const timeEnd = Cesium.JulianDate.addDays(
    timeStart,
    duration,
    new Cesium.JulianDate()
  )
  viewer.clock.startTime = timeStart.clone()
  viewer.clock.stopTime = timeEnd.clone()
  viewer.clock.currentTime = timeStart.clone()
  viewer.clock.clockRange = clockRange //UNBOUNDED(:always),CLAMPED(:stop),LOOP_STOP(:loop)
  viewer.clock.multiplier = multiplier //时间流速
  viewer.clock.shouldAnimate = true
}

onMounted(() => {
  if (!viewer) {
    initMap()
    eventLeftClick()
  }
})

defineExpose({
  pickPosition,
  getCameraInfo,
  flyToPosition,
  flyTo2DPosition,
  findLightingFlyToPosition,
  showPointHeightLightLayer,
  showPolylineHeightLightLayer,
  loadGeoJson,
  addSparkleShowPointGeometryFromDegrees,
  addPointGeometryFromDegrees,
  addPolylineGeometryFromDegrees,
  getClickPointToMap,
  add3dTile,
  showInfoWindow,
  closeInfoWindow,
  measureLine,
  clearScreen,
  addMarker,
  zoomIn,
  zoomOut,
  zoomReset,
  selectBaseMap,

  showLightEffect,

  addLightEffect,

  clearPostProcessStages,
  drawLineMeasure,
  drawAreaMeasure,
  drawTriangles3DMeasure,
  clearDrawMeasure,
  perimeterBufferAnalysis,
  changeDataSourcesShow,
  clearDataSourcesEntitiesByLayerId,

  clearBurstBufferEntitiesAll,

  bufferAnimation,
  clearSnowEffect,
  clearRainEffect,
  clearFogEffect,
  loadBurstBufferGeoJson,

  inundationAnalysis,
  lightingShadowAnalysis,

  update3dtilesMaxtrix,
  load3Dtiles,
  addBillboard,
  createWall,
  loadEntitiesPolyline,
  loadEntitiesPolyline2,
  addHeatmap,
  clearHeatmap,
  activeFloor,
  cameraFlyto,
  test,
  addFlashingBillboard,
  showBillboard,
  showBillboardEntity,
  addLabel
})
</script>

<style lang="scss" scoped>
.map-box {
  width: 100%;
  height: 100%;

  #cesiumContainer {
    width: 100%;
    height: 100%;
  }
}
</style>
